<?php

namespace App\Http\Controllers\Api;

use App\Exceptions\BusinessException;
use App\Http\Controllers\Controller;
use App\Http\Resources\GoodsModelResource;
use App\Models\AssetModel;
use App\Models\GoodsPicModel;
use App\Models\GoodsPicPrimaryModel;
use App\Models\SpecModel;
use App\Utils\ControllerModelTrait;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;

class SpecController extends ApiController
{
    use ControllerModelTrait;
    const CACHE_KEY = 'goodsSpec-';

    /**
     * 商品列表
     * @param Request $request
     * @return JsonResponse
     */
    public function getList(Request $request): JsonResponse
    {
        $Model = GoodsPicPrimaryModel::getModel($request);
        $paginate = $this->getPagedData($Model, $request, 'ID');
        $list = [];
        $items = json_decode(json_encode($paginate->items()), true);
        $zipList = AssetModel::whereIn('goods_id', array_column($items, 'ID'))->get();
        foreach ($paginate as $item) {
            $item->Picture = GoodsModelResource::THUMBNAIL_PREFIX . $item->Path . DIRECTORY_SEPARATOR . $item->FName;
            $zip = $zipList->where('goods_id', $item->ID)->first();
            $item->zip_id = $zip ? $zip->id : '';
            $item->zip = $zip ? $zip->file : '';
            $list[] = $item;
        }
        return $this->success($this->getPaginate($paginate, $list));
    }

    /**
     * 获取单个商品规格列表
     * @param Request $request
     * @return JsonResponse
     * @throws BusinessException
     */
    public function getGoodsSpec(Request $request): JsonResponse
    {
        $goodsId = $this->verifyNumeric('goods_id');
        $collection = SpecModel::where('goods_id', $goodsId)->select(['id', 'goods_id', 'goods_sn', 'color', 'size', 'weight', 'price', 'stock', 'private', 'thumbnail'])->get();
        $images = $collection->filter(function ($item) {
            return !empty($item->thumbnail);
        })->pluck('thumbnail', 'color')->toArray();
        $list = [];
        foreach ($collection as $item) {
            if (!$item->thumbnail)
                $item->thumbnail = $images[$item->color] ?? '';
            $thumbnail = str_replace('EnPic', 'UpLoad', $item->thumbnail);
            $item->thumbnail = str_replace('dat', 'jpg', $thumbnail);
            $list[] = $item;
        }
        return $this->success($list);
    }

    /**
     * 设置商品规格库存
     * @param Request $request
     * @return JsonResponse
     * @throws BusinessException
     */
    public function setSpecsStock(Request $request): JsonResponse
    {
        $stock = $this->verifyNumeric('stock');
        if ($request->input('goods_sn'))
            SpecModel::where('goods_sn', $request->input('goods_sn'))->update(['stock' => $stock]);
        else {
            if ($request->input('goods_id'))
                SpecModel::where('goods_id', $request->input('goods_id'))->update(['stock' => $stock]);
        }
        return $this->success();
    }

    /**
     * 获取等高等宽的方图
     * @param Request $request
     * @return JsonResponse
     */
    public function getSquareImages(Request $request): JsonResponse
    {
        $goods_id = $request->input('goods_id', '');
        $images = GoodsPicModel::where('PID', $goods_id)->where('width', '>', 1)->whereRaw('width = height')
            ->select(['Path', 'FName'])->orderByDesc('ID')->get()->each(function ($item) {
                $item->url = Controller::getImageFullUrl($item, true);
                return $item;
            });
        return $this->success($images);
    }

    /**
     * 保存规格
     * @param Request $request
     * @return JsonResponse
     * @throws BusinessException
     */
    public function saveSpecs(Request $request): JsonResponse
    {
        $goods_id = $this->verifyInteger('goods_id');
        $specs = $request->input('specs');
        $goods = GoodsPicPrimaryModel::where('ID', $goods_id)->first();
        if ($specs)
            $goods = $this->setGoodsSpec($goods, $specs);
        if ($request->input('zip_id'))
            $goods = $this->setGoodsZip($goods, $request);
        $goods->save();
        return $this->success(['count' => count($specs)]);
    }

    /**
     * 批量保存修改
     * @param Request $request
     * @return JsonResponse
     * @throws BusinessException
     */
    public function saveChangeSpec(Request $request): JsonResponse
    {
        $id = $this->verifyId('id');
        $postData = $request->only(['goods_id', 'goods_sn', 'size', 'color', 'weight', 'price', 'stock', 'stock', 'thumbnail']);
        $spec = SpecModel::where('id', $id)->first();
        // 批量
        if ($request->input('change_all')) {
            $specData = json_decode(json_encode($spec), true);
            foreach (['color', 'size', 'weight', 'price', 'stock'] as $key) {
                if ($specData[$key] != $postData[$key])
                    SpecModel::where('goods_id', $postData['goods_id'])->where($key, $specData[$key])->update([$key => $postData[$key]]);
            }
        } else {
            // 提交尺寸，单条更新
            $request->input('size') ? SpecModel::where('id', $id)->update($postData)
                : SpecModel::where('goods_id', $postData['goods_id'])->where('color', $postData['color'])->update(['thumbnail' => $postData['thumbnail']]);
        }
        self::setSpecCache($request->input('goods_id'));
        return $this->success();
    }

    /**
     * 删除规格
     * @param Request $request
     * @return JsonResponse
     * @throws BusinessException
     */
    public function deleteSpec(Request $request): JsonResponse
    {
        $ids = $this->verifyString('ids');
        SpecModel::whereIn('id', explode(',', $ids))->delete();
        return $this->success();
    }

    /**
     * 变更库存
     * @param Request $request
     * @return JsonResponse
     */
    public function setStock(Request $request): JsonResponse
    {
        $id = $request->input('id');
        $spec = SpecModel::where('id', $id)->first();
        if ($spec) {
            $spec->stock = $request->input('stock', 0);
            $spec->save();
            self::setSpecCache($spec->goods_id);
        }
        return $this->success([]);
    }

    /**
     * 获取商品规格缓存
     * @param $goods_id
     * @return mixed
     */
    public static function getSpecCache($goods_id): mixed
    {
        if (!Cache::has(self::CACHE_KEY . $goods_id))
            self::setSpecCache($goods_id);
        return Cache::get(self::CACHE_KEY . $goods_id);
    }

    /**
     * 设置规格缓存
     * @param $goods_id
     * @return void
     */
    public static function setSpecCache($goods_id): void
    {
        Cache::put(self::CACHE_KEY . $goods_id, SpecModel::where('goods_id', $goods_id)->get());
    }

    /**
     * 更新商品规格
     * @param $goods
     * @param $specs
     * @return mixed
     */
    private function setGoodsSpec($goods, $specs): mixed
    {
        $dataList = [];
        foreach ($specs as $item)
            $dataList[] = $this->getSpecData($goods->ID, $goods->SID, $item);
        SpecModel::insert($dataList);
        self::setSpecCache($goods->ID);
        $goods->skuFlag = 1;
        return $goods;
    }

    /**
     * 更新商品压缩包
     * @param $goods
     * @param $request
     * @return mixed
     */
    private function setGoodsZip($goods, $request): mixed
    {
        AssetModel::where('goods_id', $request->input('goods_id', 0))->update(['goods_id' => 0]);
        AssetModel::where('id', $request->input('zip_id'))
            ->update([
                'goods_id' => $request->input('goods_id'),
                'goods_name' => $request->input('goods_name')
            ]);
        $goods->IsEncry = 2;
        //GoodsPicModel::where('ID', $request->input('goods_id'))->update(['IsEncry' => 2]);
        return $goods;
    }

    /**
     * 转换规格数组
     * @param $goods_id
     * @param $sid
     * @param $item
     * @return array
     */
    private function getSpecData($goods_id, $sid, $item): array
    {
        if ($item && $item['weight'] > 0 && $item['price'] > 0) {
            $datetime = Carbon::now()->toDateTimeString();
            return [
                'goods_id'    => $goods_id,
                'goods_name'  => request()->input('goods_name', ''),
                'goods_sn'    => $item['goods_sn'] ? $item['goods_sn'] : $this->setGoodsSn(),
                'color'       => $item['color'],
                'size'        => $item['size'],
                'weight'      => $item['weight'],
                'price'       => $item['price'],
                'stock'       => $item['stock'],
                'sid'         => $sid,
                'thumbnail'   => $item['thumbnail'],
                'private'     => $item['private'] ? 1 : 0,
                'created_at'  => $datetime,
                'updated_at'  => $datetime,
            ];
        } else
            return [];
    }

    /**
     * 生成规格编号
     * @return string
     */
    private function setGoodsSn(): string
    {
        return 'M' . intval(Carbon::now()->getPreciseTimestamp(3))
            . rand(100, 999);
    }
}
